use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::{Mutex, RwLock};

use shared::{ChatNode, TerminalInfo, WebShareProxyInfo};

/// Connection state for the Tauri application
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionState {
    pub node_id: Option<String>,
    pub ticket: Option<String>,
    pub is_connected: bool,
    pub connected_terminals: Vec<TerminalInfo>,
    pub active_proxies: Vec<WebShareProxyInfo>,
    pub peers: Vec<String>,
}

impl Default for ConnectionState {
    fn default() -> Self {
        Self {
            node_id: None,
            ticket: None,
            is_connected: false,
            connected_terminals: Vec::new(),
            active_proxies: Vec::new(),
            peers: Vec::new(),
        }
    }
}

/// Tauri application state
pub struct RitermState {
    pub chat_node: Option<ChatNode>,
    pub connection_state: Arc<RwLock<ConnectionState>>,
    pub event_handlers: Arc<Mutex<Vec<String>>>, // Store event handler callbacks
    pub event_broadcaster: Arc<Mutex<Option<EventBroadcaster>>>,
}

impl RitermState {
    pub fn new() -> Self {
        Self {
            chat_node: None,
            connection_state: Arc::new(RwLock::new(ConnectionState::default())),
            event_handlers: Arc::new(Mutex::new(Vec::new())),
            event_broadcaster: Arc::new(Mutex::new(None)),
        }
    }

    pub async fn update_connection_state<F>(&self, updater: F) -> Result<()>
    where
        F: FnOnce(&mut ConnectionState),
    {
        let mut state = self.connection_state.write().await;
        updater(&mut state);
        Ok(())
    }

    pub async fn get_connection_state(&self) -> ConnectionState {
        self.connection_state.read().await.clone()
    }

    pub async fn set_event_broadcaster(&self, broadcaster: EventBroadcaster) {
        let mut guard = self.event_broadcaster.lock().await;
        *guard = Some(broadcaster);
    }

    pub async fn get_event_broadcaster(&self) -> Option<EventBroadcaster> {
        let guard = self.event_broadcaster.lock().await;
        guard.clone()
    }

    // Helper method to clone the Arc for use in async contexts
    pub fn arc(self: &Arc<Self>) -> &Arc<Self> {
        self
    }
}

/// Configuration for connecting to remote CLI
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionConfig {
    pub ticket: String,
    pub nickname: Option<String>,
    pub auto_reconnect: bool,
    pub secret_key: Option<String>, // IROH_SECRET
}

impl Default for ConnectionConfig {
    fn default() -> Self {
        Self {
            ticket: String::new(),
            nickname: Some("riterm-client".to_string()),
            auto_reconnect: true,
            secret_key: None,
        }
    }
}

/// Terminal session information for UI
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TerminalSession {
    #[serde(rename = "sessionId")]
    pub session_id: String,
    pub name: Option<String>,
    pub status: String,
    pub created_at: u64,
    pub last_activity: u64,
    pub size: TerminalSize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TerminalSize {
    pub rows: u32,
    pub cols: u32,
}

impl From<shared::TerminalSize> for TerminalSize {
    fn from(size: shared::TerminalSize) -> Self {
        Self {
            rows: size.rows,
            cols: size.cols,
        }
    }
}

impl From<TerminalInfo> for TerminalSession {
    fn from(info: TerminalInfo) -> Self {
        Self {
            session_id: info.session_id,
            name: info.name,
            status: info.status,
            created_at: info.created_at,
            last_activity: info.last_activity,
            size: info.size.into(),
        }
    }
}

/// Message types for real-time communication
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
#[allow(dead_code)]
pub enum ClientMessage {
    Connect(ConnectionConfig),
    Disconnect,
    CreateTerminal {
        session_id: String,
        shell_path: Option<String>,
        name: Option<String>,
    },
    SendTerminalInput {
        session_id: String,
        data: Vec<u8>,
    },
    ResizeTerminal {
        session_id: String,
        rows: u32,
        cols: u32,
    },
    CloseTerminal {
        session_id: String,
    },
    RenameTerminal {
        session_id: String,
        new_name: Option<String>,
    },
    SendWebShare {
        local_port: u16,
        public_port: u16,
    },
    SendWebUnshare {
        public_port: u16,
    },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ServerMessage {
    Connected { node_id: String, ticket: String },
    Disconnected,
    TerminalCreated { session_id: String },
    TerminalOutput { session_id: String, data: Vec<u8> },
    TerminalStatus { session_id: String, status: String },
    TerminalStateChanged { terminals: Vec<TerminalSession> },
    NodeJoined { node_id: String },
    NodeLeft { node_id: String },
    WebShareStarted { local_port: u16, public_port: u16 },
    WebShareStopped { public_port: u16 },
    Error { message: String },
}

/// Event broadcaster for real-time updates
#[derive(Clone)]
pub struct EventBroadcaster {
    listeners: Arc<Mutex<Vec<tokio::sync::mpsc::UnboundedSender<ServerMessage>>>>,
}

impl EventBroadcaster {
    pub fn new() -> Self {
        Self {
            listeners: Arc::new(Mutex::new(Vec::new())),
        }
    }

    pub async fn subscribe(&self) -> tokio::sync::mpsc::UnboundedReceiver<ServerMessage> {
        let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
        self.listeners.lock().await.push(tx);
        rx
    }

    pub async fn broadcast(&self, message: ServerMessage) {
        let mut listeners = self.listeners.lock().await;
        listeners.retain(|tx| tx.send(message.clone()).is_ok());
    }
}

impl Default for EventBroadcaster {
    fn default() -> Self {
        Self::new()
    }
}
